package Tools.Lighting;

import java.util.ArrayList;
import java.util.List;

import Game.GameHelper;
import GameMath.GPoint;

/** Light point class
 * @author Aikidos
 */
public class LightPoint implements ILight {

	/** Light manager */
	private LightManager _lightManager;
	
	/** Light position */
	private GPoint _position = new GPoint();
	
	/** Light range */
	private int _range = 5;
	
	/** Current maximum range for animation RANDOM_RANGE */
	private int _animMaxRange = 0;
	
	/** Light animation */
	private EAnimations _anim = EAnimations.NONE;
	
	/** Animation delay */
	private int _animDelay = 250;
	
	/** Animation timer */
	private int _animTimer = 0;
	
	public enum EAnimations {
		NONE,
		RANDOM_RANGE
	}
	
	/** Returns true if position is valid
	 * @param lightMap - Light map
	 * @param pos - Position
	 * @return True if position is valid
	 */
	private boolean validPosition(LightMap lightMap, GPoint pos) {	
		return (pos.x < lightMap.getSize().width)
				&& (pos.y < lightMap.getSize().height)
				&& (pos.x >= 0)
				&& (pos.y >= 0);
	}
	
	public LightPoint(LightManager lightManager) {
		_lightManager = lightManager;
	}
	
	@Override
	public GPoint getPosition() {
		return _position;
	}

	@Override
	public int getRange() {
		return _range;
	}

	/** Returns light animation 
	 * @return Light animation
	 */
	public EAnimations getAnima() {
		return _anim;
	}
	
	/** Returns animation delay time
	 * @return Delay time
	 */
	public int getAnimDelay() {
		return _animDelay;
	}
	
	@Override
	public void setPosition(GPoint pos) {
		_position.set(pos);
	}

	@Override
	public void setRange(int range) {
		_range = range;
	}

	/** Set light animation 
	 * @param animation - Light animation
	 */
	public void setAnim(EAnimations animation) {
		switch (animation)
		{
		case NONE:
			if (_anim == EAnimations.RANDOM_RANGE)
				_range = _animMaxRange;
			break;
		case RANDOM_RANGE:
			_animMaxRange = _range;
			break;
		}
		
		_anim = animation;
	}

	/** Set animation delay time
	 * @param delay - Delay time
	 */
	public void setAnimDelay(int delay) {
		_animDelay = delay;
	}
	
	@Override
	public void calcLighting(LightMap lightMap, boolean[][] solidMap) {
		List<GPoint> lstPass = new ArrayList<GPoint>();
		lstPass.add(new GPoint(_position));
		
		// Set start point illumination
		lightMap.getMap()[_position.x][_position.y].addIllumination(this, 1.f);
		
		float baseIllumination = 1.f;
		
		for (int i = 0; i < lstPass.size(); i++) {
			GPoint newPos = new GPoint(lstPass.get(i));
			
			baseIllumination = lightMap.getMap()[newPos.x][newPos.y].getIlluminationByLight(this);
			if (baseIllumination == 0) continue;
			if (solidMap[newPos.x][newPos.y]) continue;
			
			// Left
			newPos.x -= 1;
			if (validPosition(lightMap, newPos)
					&& !lightMap.getMap()[newPos.x][newPos.y].containsLight(this))
			{
				lstPass.add(new GPoint(newPos));
				
				// Set illumination
				lightMap.getMap()[newPos.x][newPos.y].addIllumination(this, baseIllumination - (1.f / _range));
			}
			
			// Top
			newPos.set(lstPass.get(i));
			newPos.y -= 1;
			if (validPosition(lightMap, newPos)
					&& !lightMap.getMap()[newPos.x][newPos.y].containsLight(this))
			{
				lstPass.add(new GPoint(newPos));
				
				// Set illumination
				lightMap.getMap()[newPos.x][newPos.y].addIllumination(this, baseIllumination - (1.f / _range));
			}
			
			// Right 
			newPos.set(lstPass.get(i));
			newPos.x += 1;
			if (validPosition(lightMap, newPos)
					&& !lightMap.getMap()[newPos.x][newPos.y].containsLight(this))
			{
				lstPass.add(new GPoint(newPos));
				
				// Set illumination
				lightMap.getMap()[newPos.x][newPos.y].addIllumination(this, baseIllumination - (1.f / _range));
			}
			
			// Bottom
			newPos.set(lstPass.get(i));
			newPos.y += 1;
			if (validPosition(lightMap, newPos)
					&& !lightMap.getMap()[newPos.x][newPos.y].containsLight(this))
			{
				lstPass.add(new GPoint(newPos));
				
				// Set illumination
				lightMap.getMap()[newPos.x][newPos.y].addIllumination(this, baseIllumination - (1.f / _range));
			}
		}
	}

	@Override
	public void update(int delta) {
		// Animation
		if (_anim == EAnimations.RANDOM_RANGE) {
			if (_animTimer >= _animDelay){
				_animTimer = 0;
				_range = GameHelper.getRandom().nextInt(_animMaxRange - (_animMaxRange / 2)) + (_animMaxRange / 2);
				_lightManager.calcLighting();
			}
			else
				_animTimer += delta;
		}
	}

}
